home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_number / small_fraction.e < prev    next >
Text File  |  2000-03-25  |  8KB  |  342 lines

  1. -- This file is  free  software, which  comes  along  with  SmallEiffel. This
  2. -- software  is  distributed  in the hope that it will be useful, but WITHOUT 
  3. -- ANY  WARRANTY;  without  even  the  implied warranty of MERCHANTABILITY or
  4. -- FITNESS  FOR A PARTICULAR PURPOSE. You can modify it as you want, provided
  5. -- this header is kept unaltered, and a notification of the changes is added.
  6. -- You  are  allowed  to  redistribute  it and sell it, alone or as a part of 
  7. -- another product.
  8. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  9. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  10. --                       http://SmallEiffel.loria.fr
  11. --
  12. class SMALL_FRACTION
  13. --
  14. -- To implement NUMBER (do not use this class, see NUMBER).
  15. --
  16.           
  17. inherit ABSTRACT_FRACTION;
  18.    
  19. creation make, make_from_integer
  20.    
  21. feature 
  22.    
  23.    is_positive: BOOLEAN is
  24.       do
  25.      Result := numerator >= 0;
  26.       end;
  27.  
  28.    is_negative: BOOLEAN is
  29.       do
  30.      Result := numerator < 0;
  31.       end;
  32.  
  33.    is_equal(other: like Current): BOOLEAN is  
  34.       do   
  35.      Result := standard_is_equal(other);
  36.       end;  
  37.  
  38.    to_double: DOUBLE is
  39.       do
  40.      Result := numerator / denominator;
  41.       end;   
  42.       
  43.    prefix "-": NUMBER is  
  44.       do   
  45.      !SMALL_FRACTION!Result.make(-numerator,denominator); 
  46.       end;   
  47.    
  48.    infix "+"(other: NUMBER): NUMBER is  
  49.       do   
  50.      Result := other.add_with_small_fraction(Current); 
  51.       end;  
  52.  
  53.    infix "@+"(other: INTEGER): NUMBER is
  54.      -- Sum of 'Current' and 'other'.  
  55.       local
  56.      sum : ABSTRACT_INTEGER;
  57.       do        
  58.      sum ?= small_numerator + (small_denominator @* other);
  59.      check
  60.         sum /= Void;
  61.      end;
  62.      Result := from_abstract_integer_and_integer(sum,denominator);
  63.       end;  
  64.  
  65.    infix "*"(other: NUMBER): NUMBER is
  66.       do
  67.      Result := other.multiply_with_small_fraction(Current);
  68.       end;
  69.    
  70.    infix "@*"(other: INTEGER): NUMBER is  
  71.       local  
  72.      tmp: ABSTRACT_INTEGER;
  73.       do 
  74.      if (other = 1) then
  75.         Result := Current;
  76.      elseif (other = -1) then
  77.         Result := -Current;
  78.      else
  79.         tmp ?= small_numerator @* other;
  80.         check
  81.            tmp /= Void;
  82.         end;
  83.         Result := from_abstract_integer_and_integer(tmp,denominator);
  84.      end;
  85.       end;  
  86.    
  87.    infix "@/"(other: INTEGER): NUMBER is  
  88.       do      
  89.      if (other = 1) then        
  90.         Result := Current;
  91.      elseif (other = -1) then
  92.         Result := -Current;
  93.      else
  94.         Result := Current * from_two_integer(1,other);
  95.      end; 
  96.       end;
  97.    
  98.    inverse: NUMBER is  
  99.       do   
  100.      if (numerator = 1) then  
  101.         Result := small_denominator; 
  102.      elseif (numerator = -1) then
  103.         Result := - small_denominator;
  104.      else  
  105.         !SMALL_FRACTION!Result.make(denominator,numerator); 
  106.      end;  
  107.       end;  
  108.  
  109.    infix "@<"(other: INTEGER): BOOLEAN is  
  110.       do
  111.      Result := to_double < other.to_double
  112.       end;      
  113.    
  114.    infix "@>"(other: INTEGER): BOOLEAN is
  115.       do
  116.       Result := to_double > other.to_double     
  117.       end;
  118.    
  119.    infix "@<="(other: INTEGER): BOOLEAN is
  120.       do
  121.       Result := to_double <= other.to_double     
  122.       end;   
  123.    
  124.    infix "@>="(other: INTEGER): BOOLEAN is
  125.       do
  126.       Result := to_double >= other.to_double     
  127.       end;   
  128.    
  129.    infix "<"(other: NUMBER): BOOLEAN is  
  130.       do   
  131.      Result := other.greater_with_small_fraction(Current); 
  132.       end;  
  133.  
  134.    infix "#=" (other: DOUBLE): BOOLEAN is
  135.       do
  136.      Result := (numerator / denominator) = other
  137.       end;
  138.      
  139.    
  140.    infix "#>"(other: DOUBLE): BOOLEAN is
  141.       do
  142.      Result := to_double > other 
  143.       end;
  144.      
  145.    infix "#>="(other: DOUBLE): BOOLEAN is
  146.       do
  147.      Result := to_double >= other
  148.       end;
  149.    
  150.    infix "#<"(other: DOUBLE): BOOLEAN is
  151.       do
  152.      Result := to_double < other
  153.       end;
  154.    
  155.    infix "#<="(other: DOUBLE): BOOLEAN is
  156.       do
  157.      Result := to_double <= other
  158.       end;
  159.      
  160.    append_in(string : STRING) is  
  161.       do   
  162.      numerator.append_in(string); 
  163.      string.append("/"); 
  164.      denominator.append_in(string); 
  165.       end;  
  166.  
  167. feature {NUMBER}
  168.    
  169.    numerator: INTEGER; 
  170.     
  171.    denominator: INTEGER; 
  172.  
  173.    small_numerator: SMALL_INTEGER is
  174.       do
  175.      !SMALL_INTEGER!Result.make(numerator);
  176.       end;
  177.    
  178.    small_denominator: SMALL_INTEGER is
  179.       do
  180.      !SMALL_INTEGER!Result.make(denominator);
  181.       end;
  182.  
  183.    add_with_large_positive_integer(other: LARGE_POSITIVE_INTEGER): NUMBER is  
  184.       local
  185.      sum: ABSTRACT_INTEGER;
  186.       do   
  187.      sum ?= (other @* denominator) @+ numerator;
  188.      check
  189.         sum /= Void;
  190.      end;     
  191.      Result := from_abstract_integer_and_integer(sum,denominator);
  192.       end;
  193.    
  194.    add_with_large_negative_integer(other: LARGE_NEGATIVE_INTEGER): NUMBER is  
  195.       local
  196.      sum: ABSTRACT_INTEGER;
  197.       do   
  198.      sum ?= (other @* denominator) @+ numerator;
  199.      check
  200.         sum /= Void;
  201.      end;
  202.      Result := from_abstract_integer_and_integer(sum,denominator);
  203.       end;
  204.       
  205.    add_with_small_fraction(other: SMALL_FRACTION): NUMBER is  
  206.       local  
  207.      sum, prod: ABSTRACT_INTEGER;
  208.      num1, num2, den1, den2: SMALL_INTEGER;
  209.       do
  210.      num1 := small_numerator;
  211.      den1 := small_denominator;
  212.      num2 := other.small_numerator;
  213.      den2 := other.small_denominator;     
  214.      sum ?= (num1 * den2) + (num2 * den1);
  215.      prod ?= den1 * den2;
  216.      check
  217.         sum /= Void;
  218.         prod /= Void;
  219.      end;
  220.      Result := from_two_abstract_integer(sum,prod);
  221.       end;  
  222.    
  223.    add_with_large_fraction (other: LARGE_FRACTION) : NUMBER is 
  224.       local
  225.      new_num, new_den: ABSTRACT_INTEGER;
  226.       do
  227.      if (other.is_negative) then
  228.         new_num ?= (-(other.denominator) @* numerator) + (-(other.numerator) @* denominator);
  229.      else
  230.         new_num ?= (other.denominator @* numerator) + (other.numerator @* denominator);
  231.      end;
  232.      new_den ?= other.denominator @* denominator;
  233.      check
  234.         new_num /= Void;
  235.         new_den /= Void;
  236.      end;
  237.      Result := from_two_abstract_integer(new_num,new_den);
  238.       end;
  239.  
  240.    
  241.    multiply_with_large_positive_integer(other: LARGE_POSITIVE_INTEGER): NUMBER is  
  242.       local
  243.      num: ABSTRACT_INTEGER;
  244.       do   
  245.      num ?= other @* numerator;
  246.      check
  247.         num /= Void;
  248.      end;
  249.      Result := from_abstract_integer_and_integer(num,denominator);
  250.       end;  
  251.    
  252.    multiply_with_large_negative_integer(other: LARGE_NEGATIVE_INTEGER): NUMBER is  
  253.       local
  254.      num: ABSTRACT_INTEGER;
  255.       do   
  256.      num ?= other @* numerator;
  257.      check
  258.         num /= Void;
  259.      end;
  260.      Result := from_abstract_integer_and_integer(num,denominator);
  261.       end;  
  262.    
  263.    multiply_with_small_fraction(other: SMALL_FRACTION): NUMBER is
  264.       local
  265.      num, den: ABSTRACT_INTEGER;
  266.       do
  267.      num ?= small_numerator * other.small_numerator;
  268.      den ?= small_denominator * other.small_denominator;
  269.      check
  270.         num /= Void;
  271.         den /= Void;
  272.      end;
  273.      Result := from_two_abstract_integer(num,den);
  274.       end;  
  275.  
  276.    multiply_with_large_fraction(other: LARGE_FRACTION): NUMBER is
  277.       local
  278.      new_num, new_den: ABSTRACT_INTEGER;
  279.       do
  280.      if other.is_negative then
  281.         new_num ?= -(other.numerator) @* numerator;
  282.      else
  283.         new_num ?= (other.numerator @* numerator);
  284.      end;
  285.      new_den ?= other.denominator @* denominator;
  286.      check
  287.         new_num /= Void;
  288.         new_den /= Void;
  289.      end;     
  290.      Result := from_two_abstract_integer(new_num,new_den);
  291.       end;
  292.  
  293.    greater_with_large_positive_integer(other: LARGE_POSITIVE_INTEGER): BOOLEAN is 
  294.       do
  295.       end;
  296.     
  297.    greater_with_large_negative_integer(other: LARGE_NEGATIVE_INTEGER): BOOLEAN is 
  298.       once
  299.      Result := true; 
  300.       end;
  301.  
  302.    greater_with_small_fraction(other: SMALL_FRACTION): BOOLEAN is  
  303.       do   
  304.      Result := to_double > other.to_double; 
  305.       end;  
  306.    
  307.    greater_with_large_fraction(other: LARGE_FRACTION): BOOLEAN is  
  308.       do   
  309.      Result := other.greater_with_small_fraction(Current);
  310.       end;  
  311.     
  312. feature {NONE}
  313.  
  314.    make(n, d: INTEGER) is  
  315.       do
  316.      if d < 0 then  
  317.         numerator := - n; 
  318.         denominator := - d; 
  319.      else  
  320.         numerator := n; 
  321.         denominator := d; 
  322.      end;  
  323.       end;  
  324.    
  325.    make_from_integer(n, d: INTEGER) is
  326.       require 
  327.      (n \\ d) /= 0
  328.       local 
  329.      pgcd : INTEGER;
  330.       do
  331.      pgcd := n.abs.gcd(d.abs);
  332.      make(n // pgcd,d // pgcd);
  333.       end;   
  334.    
  335. invariant
  336.    
  337.    numerator /= Minimum_integer;
  338.  
  339.    denominator > 1;
  340.  
  341. end -- SMALL_FRACTION
  342.